//-----------------------------------------------------------------------------
//
// CodeXS - Copyright(c) Businessware Architects cc
// Contact: Willem J Fourie
// E-mail : willemf@bware.biz
//
// This file is part of CodeXS.
//
// CodeXS is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License (GPL) as 
// published by the Free Software Foundation version 2 of the License.
//
//
// CodeXS is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with CodeXS; if not, write to:
//
// Free Software Foundation, Inc.
// 59 Temple Place
// Suite 330
// Boston
// MA  02111-1307  USA
//
//-----------------------------------------------------------------------------

using System;
using System.IO;
using System.Collections;
using System.Reflection;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using Microsoft.VisualBasic;

using CodeXS.Diagnostics;

namespace CodeXS.Application
{
	class Generator
	{
		public enum NetVersion { Default };
		// TODO: use .config file for latest value
        private static NetVersion latestVersion = NetVersion.Default;
		private static NetVersion netVersion = GetDefaultVersion();
		public static NetVersion Version
		{
			get
			{
				return netVersion;
			}
		}
		private static NetVersion GetDefaultVersion()
		{
            return NetVersion.Default;
            //int major = System.Environment.Version.Major;
            //if( (major == 1) || (major == 2) )
            //{
            //    int minor = System.Environment.Version.Minor;
            //    if( (minor == 1) && (major == 1) )
            //    {
            //        return NetVersion.NET_1_1;
            //    }
            //    if( (minor == 0) && (major == 2) )
            //    {
            //        return NetVersion.NET_2_0;
            //    }
            //}
            //throw new NotSupportedException("Supported on .NET 1.1, 2.0 environments only");
		}
		private static string GetNetVersionString(NetVersion version)
		{
			if (version == NetVersion.Default)
			{
				version = netVersion;
			}
			string str = Enum.GetName(typeof(NetVersion), version);
			str = str.Replace("NET_", "Net");
			if (version == latestVersion)
			{
				str = string.Empty;
			}
			return str;
		}
		public static string GetStandardModifierFileName()
		{
			string stdFileName =
				"CodeXS.Schema.StandardCodeModifier." +
				GetNetVersionString(netVersion) + ".dll";
			return stdFileName.Replace("..", ".");
		}
		private string binFolder;
		public string BinFolder
		{
			get
			{
				return binFolder;
			}
		}
		private string workingFolder;
		public string WorkingFolder
		{
			get
			{
				return workingFolder;
			}
		}
		private string outFolder;
		public string OutFolder
		{
			get
			{
				return outFolder;
			}
		}
		private object generator = null;
		// CHANGE: 2006-06-29:	 Version 0.57 Beta
		// Removed ISchemaObjectReader objects.
		public Generator(
			string binFolder,
			string workingFolder,
			string outFolder,
			string codeNamespace,
			CodeDomProvider codeDomProvider,
			string targetSchemaFilePath,
			string[] importSchemaFilePaths,
			CodeGeneratorOptions codeGeneratorOptions,
			string[] codeModifierAssemblyPaths,
			bool generateNow)
		{
			if (workingFolder == null)
			{
				this.workingFolder = Directory.GetCurrentDirectory();
			}
			else
			{
				this.workingFolder = workingFolder;
			}
			if ( ! this.workingFolder.EndsWith("\\"))
			{
				this.workingFolder += "\\";
			}
			if (outFolder == null)
			{
				this.outFolder = this.workingFolder;
			}
			else
			{
				this.outFolder = outFolder;
			}
			if ( ! this.outFolder.EndsWith("\\"))
			{
				this.outFolder += "\\";
			}
			// If the log is null, create a new log
			if(Diagnostics.Log.DefaultLog == null)
			{
				Diagnostics.Log.DefaultLog = 
					new Diagnostics.Log(Diagnostics.Log.LogDestination.LogFile);
				string logFilePath = Diagnostics.Log.DefaultLog.LogFilePath;
				Diagnostics.Log.DefaultLog.LogFilePath =
					this.outFolder + logFilePath;
				Diagnostics.Log.DefaultLog.Delete();
			}
			Assembly asm = null;
			if (binFolder == null)
			{
				asm = Assembly.GetExecutingAssembly();
				FileInfo fi = new FileInfo(asm.Location);
				this.binFolder = fi.Directory.FullName;
			}
			else
			{
				this.binFolder = binFolder;
			}
			if ( ! this.binFolder.EndsWith("\\"))
			{
				this.binFolder += "\\";
			}
			if (codeModifierAssemblyPaths != null)
			{
				ArrayList paths = new ArrayList();
				foreach (string s in codeModifierAssemblyPaths)
				{
					paths.Add(BinFolder + s);
				}
				codeModifierAssemblyPaths = (string[])paths.ToArray(typeof(string));
			}
			string generatorFilePath =
				"CodeXS.Schema." +
				GetNetVersionString(netVersion) + ".dll";
			generatorFilePath = BinFolder + generatorFilePath.Replace("..", ".");
			asm = Assembly.LoadFile(generatorFilePath);
			try
			{
				generator = asm.CreateInstance(
					"CodeXS.Schema.CodeGenerator",
					false,
					BindingFlags.CreateInstance,
					null,
					new object[]
				{
					outFolder,
					codeNamespace,
					codeDomProvider,
					targetSchemaFilePath,
					importSchemaFilePaths,
					codeGeneratorOptions,
					codeModifierAssemblyPaths,
					generateNow
				},
					null,
					null);
			}
			catch(Exception e)
			{
				Log.DefaultLog.LogException(e);
			}
		}
		public string[] CodeFilePaths
		{
			get
			{
				if (generator != null)
				{
					PropertyInfo propInfo = 
						generator.GetType().GetProperty("CodeFilePaths");
					if (propInfo != null)
					{
						return propInfo.GetValue(generator, null) as string[];
					}
				}
				return null;
			}
		}
		public string[] Warnings
		{
			get
			{
				if (generator != null)
				{
					PropertyInfo propInfo =
						generator.GetType().GetProperty("Warnings");
					if (propInfo != null)
					{
						return propInfo.GetValue(generator, null) as string[];
					}
				}
				return null;
			}
		}
	}
}
